function signalTx = WiSiL_Precoder_precoding(mappedSignal, transmitter)
% WISIL_PRECODER_PRECODING MIMO Precoder. 
%
%   SIGNALTX = WiSiL_Precoder_precoding( MAPPEDSIGNAL, TRANSMITTER ) 
%   performs the precoding for multiple antenna transmission according to 
%   3GPP TS 36.211 V8.2.0. 
%   This precoding is done in different ways, for spatial multiplexing or
%   spatial diversity.
%   MAPPEDSIGNAL is the modulated Signal mapped onto layers.
%   TRANSMITTER is a parameter structure containing the fields:
%              .txNum, the number of transmitter antennas.
%              .scheme, one of the following strings: 'none' (allowed only
%               for single antenna transmission), 'diversity' or 
%               'multiplexing'.
%              .layers, the number of layers.
%
%   SIGNALTX is the transmitted Signal, in which each column represents a 
%   vector to be transmitted at one antenna.

% History
% 12/05/2009 Rafhael Amorim
%   created

scheme = transmitter.scheme;
layers = transmitter.layers;
txNum = transmitter.txNum;

% Invokes the codebook which contains the precoding matrixes. 
precodingMatrix = WiSiL_Precoder_codebook ( scheme );


if strcmpi(scheme,'none')
    signalTx = (mappedSignal).';
end
                              
% For more than 1 Antenna Port:
if strcmpi(scheme,'diversity') % If Spatial Multiplexing is deployed.
    
    if txNum == 2;
    
    auxiliar=[real(mappedSignal); imag(mappedSignal)];
    y = precodingMatrix*auxiliar;
    signalTx(1,:) = reshape(y(1:2:3,:),1,[]);
    signalTx(2,:) = reshape(y(2:2:4,:),1,[]);
    
    elseif txNum==4
    
    auxiliar=[real(mappedSignal); imag(mappedSignal)];
    y = precodingMatrix*auxiliar;
    signalTx(1,:) = reshape(y(1:4:end,:),1,4*length(y));
    signalTx(2,:) = reshape(y(2:4:end,:),1,4*length(y));
    signalTx(3,:) = reshape(y(3:4:end,:),1,4*length(y));
    signalTx(4,:) = reshape(y(4:4:end,:),1,4*length(y));
    
    end
    
elseif strcmpi (scheme,'multiplexing') 

    CDD = transmitter.CDD;
    codebookIndex = transmitter.codebookIndex;
    
    % Create the correct parameters for zero Cyclic Delay Diversity.
    if strcmpi(CDD,'zero')
       
        D = eye(txNum); % Support Matrix for CDD.
        W = precodingMatrix{codebookIndex,layers}(:,:); % Precoding Matrix, properly choosen at codebook.
        
        
        y=D*W*mappedSignal; % Output of the precoder.
        
        signalTx=y;
        
    %Create the correct parameters for small Cyclic Delay Diversity.     
    elseif strcmpi(CDD,'small')
       
        D = eye(txNum); % Support Matrix for CDD.
        W = precodingMatrix{codebookIndex,layers}(:,:); % Precoding Matrix, properly choosen at codebook.
        signalTx=D*W*mappedSignal;
    
    %Create the correct parameters for large Cyclic Delay Diversity.
    elseif strcmpi(CDD,'large')
        
        W = precodingMatrix{codebookIndex,layers}(:,:); % Precoding Matrix, properly choosen at codebook.
        
        if layers==1
            U=1; % auxiliar Matrix
            D=1; % Support Matrix for CDD.
            
            for aux=1:length(mappedSignal)
                signalTx(:,aux)=W*D*U*mappedSignal(:,aux); %Output of the precoder.
            end
            
        elseif layers==2
            U=(1/sqrt(2))*[1 1; 1 -1]; % auxiliar Matrix
            
            for aux= 1: length(mappedSignal)
                D=[1 0; 0 exp(-1i*pi*aux)]; % Support Matrix for CDD.
                signalTx(:,aux)=W*D*U*mappedSignal(:,aux); % Transmitted Signal
            end
            
        elseif layers==3
            U=(1/sqrt(3))*[1 1 1;...
                           1 exp(-1i*2*pi/3) exp(-1i*4*pi/3)...
                           1 exp(-1i*4*pi/3) exp(-1i*8*pi/3)]; % auxiliar Matrix
            
            for aux= 1: length(mappedSignal)
                D=[1 0 0;...
                  0 exp(-1i*2*pi*aux/3) 0;...
                  0 0 exp(-1i*4*pi*aux/3)]; % Support Matrix for CDD.
                signalTx(:,aux)=W*D*U*mappedSignal(:,aux); % Transmitted Signal
            end
                   
        elseif layers==4
            U=(1/2)*[1 1 1 1;...
                     1 exp(-1i*pi/2) exp(-1i*pi) exp(-1i*3*pi/2);...
                     1 exp(-1i*pi) exp(-1i*2*pi) exp(-1i*3*pi);...
                     1 exp(-1i*3*pi/2) exp(-1i*3*pi) exp(-1i*9*pi/2)]; % auxiliar Matrix
              
            for aux= 1: length(mappedSignal)
                D=[1 0 0 0;...
                  0 exp(-1i*pi*aux/2) 0 0;...
                  0 0 exp(-1i*4*pi/4) 0;...
                  0 0 0 exp(-1i*3*pi/2)]; % Support Matrix for CDD.
                 signalTx(:,aux)=W*D*U*mappedSignal(:,aux); % Transmitted Signal
            end
                     
        end
    end
end

signalTx = (signalTx).';